package com.chenfan.common.extension.util;

import com.chenfan.common.extension.util.wrapper.CallableWrapper;
import com.chenfan.common.extension.util.wrapper.RunnableWrapper;

import java.util.concurrent.*;

/**
 * 智能线程池执行器
 * @author wulg
 * @date 2021-11-17
 **/
public class SmartExecutorService extends ThreadPoolExecutor {

    private final static int AVAILABLE_PROCESSORS = Runtime.getRuntime().availableProcessors();

    public static ExecutorService newFixedThreadPool() {
        return newFixedThreadPool(AVAILABLE_PROCESSORS);
    }

    public static ExecutorService newSingleThreadExecutor(int nThreads) {
        return newFixedThreadPool(1);
    }

    public static ExecutorService newFixedThreadPool(int nThreads) {
        SmartExecutorService executorService = new SmartExecutorService(nThreads, nThreads,60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
        ApplicationShutdownHook.add(() -> executorService.shutdown());
        return executorService;
    }

    public static ExecutorService newCachedThreadPool() {
        return newCachedThreadPool(0, Integer.MAX_VALUE);
    }

    public static ExecutorService newCachedThreadPool(int minThreads, int maxThreads) {
        SmartExecutorService executorService = new SmartExecutorService(minThreads, maxThreads,60L, TimeUnit.SECONDS,new SynchronousQueue<>());
        ApplicationShutdownHook.add(() -> executorService.shutdown());
        return executorService;
    }

    public SmartExecutorService(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
    }

    public SmartExecutorService(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
    }

    public SmartExecutorService(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler);
    }

    public SmartExecutorService(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
    }


    @Override
    public void execute(Runnable command) {
        super.execute(new RunnableWrapper(command));
    }

    @Override
    public Future<?> submit(Runnable task) {
        return super.submit(new RunnableWrapper(task));
    }

    @Override
    public <T> Future<T> submit(Runnable task, T result) {
        return super.submit(new RunnableWrapper(task), result);
    }

    @Override
    public <T> Future<T> submit(Callable<T> task) {
        return super.submit(new CallableWrapper(task));
    }
}
